/*
	Lens by HTML5 UP
	html5up.net | @ajlkn
	Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
*/

var main = (function ($) {
  var _ = {

    /**
     * Settings.
     * @var {object}
     */
    settings: {

      // Preload all images.
      preload: false,

      // Slide duration (must match "duration.slide" in _vars.scss).
      slideDuration: 500,

      // Layout duration (must match "duration.layout" in _vars.scss).
      layoutDuration: 750,

      // Thumbnails per "row" (must match "misc.thumbnails-per-row" in _vars.scss).
      thumbnailsPerRow: 2,

      // Side of main wrapper (must match "misc.main-side" in _vars.scss).
      mainSide: 'right'

    },

    /**
     * Window.
     * @var {jQuery}
     */
    $window: null,

    /**
     * Body.
     * @var {jQuery}
     */
    $body: null,

    /**
     * Main wrapper.
     * @var {jQuery}
     */
    $main: null,

    /**
     * Thumbnails.
     * @var {jQuery}
     */
    $thumbnails: null,

    /**
     * Viewer.
     * @var {jQuery}
     */
    $viewer: null,

    /**
     * Toggle.
     * @var {jQuery}
     */
    $toggle: null,

    /**
     * Nav (next).
     * @var {jQuery}
     */
    $navNext: null,

    /**
     * Nav (previous).
     * @var {jQuery}
     */
    $navPrevious: null,

    /**
     * Slides.
     * @var {array}
     */
    slides: [],

    /**
     * Current slide index.
     * @var {integer}
     */
    current: null,

    /**
     * Lock state.
     * @var {bool}
     */
    locked: false,

    /**
     * Keyboard shortcuts.
     * @var {object}
     */
    keys: {

      // Escape: Toggle main wrapper.
      27: function () {
        _.toggle();
      },

      // Up: Move up.
      38: function () {
        _.up();
      },

      // Down: Move down.
      40: function () {
        _.down();
      },

      // Space: Next.
      32: function () {
        _.next();
      },

      // Right Arrow: Next.
      39: function () {
        _.next();
      },

      // Left Arrow: Previous.
      37: function () {
        _.previous();
      }

    },

    /**
     * Initialize properties.
     */
    initProperties: function () {

      // Window, body.
      _.$window = $(window);
      _.$body = $('body');

      // Thumbnails.
      _.$thumbnails = $('#thumbnails');

      // Viewer.
      _.$viewer = $(
          '<div id="viewer">' +
          '<div class="inner">' +
          '<div class="nav-next"></div>' +
          '<div class="nav-previous"></div>' +
          '<div class="toggle"></div>' +
          '</div>' +
          '</div>'
      ).appendTo(_.$body);

      // Nav.
      _.$navNext = _.$viewer.find('.nav-next');
      _.$navPrevious = _.$viewer.find('.nav-previous');

      // Main wrapper.
      _.$main = $('#main');

      // Toggle.
      $('<div class="toggle"></div>')
      .appendTo(_.$main);

      _.$toggle = $('.toggle');

      // IE<9: Fix viewer width (no calc support).
      if (skel.vars.IEVersion < 9) {
        _.$window
        .on('resize', function () {
          window.setTimeout(function () {
            _.$viewer.css('width', _.$window.width() - _.$main.width());
          }, 100);
        })
        .trigger('resize');
      }

    },

    /**
     * Initialize events.
     */
    initEvents: function () {

      // Window.

      // Remove is-loading-* classes on load.
      _.$window.on('load', function () {

        _.$body.removeClass('is-loading-0');

        window.setTimeout(function () {
          _.$body.removeClass('is-loading-1');
        }, 100);

        window.setTimeout(function () {
          _.$body.removeClass('is-loading-2');
        }, 100 + Math.max(_.settings.layoutDuration - 150, 0));

      });

      // Disable animations/transitions on resize.
      var resizeTimeout;

      _.$window.on('resize', function () {

        _.$body.addClass('is-loading-0');
        window.clearTimeout(resizeTimeout);

        resizeTimeout = window.setTimeout(function () {
          _.$body.removeClass('is-loading-0');
        }, 100);

      });

      // Viewer.

      // Hide main wrapper on tap (<= medium only).
      _.$viewer.on('touchend', function () {

        if (skel.breakpoint('medium').active) {
          _.hide();
        }

      });

      // Touch gestures.
      _.$viewer
      .on('touchstart', function (event) {

        // Record start position.
        _.$viewer.touchPosX = event.originalEvent.touches[0].pageX;
        _.$viewer.touchPosY = event.originalEvent.touches[0].pageY;

      })
      .on('touchmove', function (event) {

        // No start position recorded? Bail.
        if (_.$viewer.touchPosX === null
            || _.$viewer.touchPosY === null) {
          return;
        }

        // Calculate stuff.
        var diffX = _.$viewer.touchPosX - event.originalEvent.touches[0].pageX,
            diffY = _.$viewer.touchPosY - event.originalEvent.touches[0].pageY;
        boundary = 20,
            delta = 50;

        // Swipe left (next).
        if ((diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta)) {
          _.next();
        }// Swipe right (previous).
        else if ((diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1
            * delta))) {
          _.previous();
        }

        // Overscroll fix.
        var th = _.$viewer.outerHeight(),
            ts = (_.$viewer.get(0).scrollHeight - _.$viewer.scrollTop());

        if ((_.$viewer.scrollTop() <= 0 && diffY < 0)
            || (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {

          event.preventDefault();
          event.stopPropagation();

        }

      });

      // Main.

      // Touch gestures.
      _.$main
      .on('touchstart', function (event) {

        // Bail on xsmall.
        if (skel.breakpoint('xsmall').active) {
          return;
        }

        // Record start position.
        _.$main.touchPosX = event.originalEvent.touches[0].pageX;
        _.$main.touchPosY = event.originalEvent.touches[0].pageY;

      })
      .on('touchmove', function (event) {

        // Bail on xsmall.
        if (skel.breakpoint('xsmall').active) {
          return;
        }

        // No start position recorded? Bail.
        if (_.$main.touchPosX === null
            || _.$main.touchPosY === null) {
          return;
        }

        // Calculate stuff.
        var diffX = _.$main.touchPosX - event.originalEvent.touches[0].pageX,
            diffY = _.$main.touchPosY - event.originalEvent.touches[0].pageY;
        boundary = 20,
            delta = 50,
            result = false;

        // Swipe to close.
        switch (_.settings.mainSide) {

          case 'left':
            result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX
                > delta);
            break;

          case 'right':
            result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX
                < (-1 * delta));
            break;

          default:
            break;

        }

        if (result) {
          _.hide();
        }

        // Overscroll fix.
        var th = _.$main.outerHeight(),
            ts = (_.$main.get(0).scrollHeight - _.$main.scrollTop());

        if ((_.$main.scrollTop() <= 0 && diffY < 0)
            || (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {

          event.preventDefault();
          event.stopPropagation();

        }

      });
      // Toggle.
      _.$toggle.on('click', function () {
        _.toggle();
      });

      // Prevent event from bubbling up to "hide event on tap" event.
      _.$toggle.on('touchend', function (event) {
        event.stopPropagation();
      });

      // Nav.
      _.$navNext.on('click', function () {
        _.next();
      });

      _.$navPrevious.on('click', function () {
        _.previous();
      });

      // Keyboard shortcuts.

      // Ignore shortcuts within form elements.
      _.$body.on('keydown', 'input,select,textarea', function (event) {
        event.stopPropagation();
      });

      _.$window.on('keydown', function (event) {

        // Ignore if xsmall is active.
        if (skel.breakpoint('xsmall').active) {
          return;
        }

        // Check keycode.
        if (event.keyCode in _.keys) {

          // Stop other events.
          event.stopPropagation();
          event.preventDefault();

          // Call shortcut.
          (_.keys[event.keyCode])();

        }

      });

    },

    /**
     * Initialize viewer.
     */
    initViewer: function () {

      // Bind thumbnail click event.
      _.$thumbnails
      .on('click', '.thumbnail', function (event) {

        var $this = $(this);

        // Stop other events.
        event.preventDefault();
        event.stopPropagation();

        // Locked? Blur.
        if (_.locked) {
          $this.blur();
        }

        // Switch to this thumbnail's slide.
        _.switchTo($this.data('index'));

      });

      // Create slides from thumbnails.
      _.$thumbnails.children()
      .each(function () {

        var $this = $(this),
            $thumbnail = $this.children('.thumbnail'),
            s;

        // Slide object.
        s = {
          $parent: $this,
          $slide: null,
          $slideImage: null,
          $slideCaption: null,
          url: $thumbnail.attr('href'),
          loaded: false
        };

        // Parent.
        $this.attr('tabIndex', '-1');

        // Slide.

        // Create elements.
        s.$slide = $(
            '<div class="slide"><div class="caption"></div><div class="image"></div></div>');

        // Image.
        s.$slideImage = s.$slide.children('.image');

        // Set background stuff.
        s.$slideImage
        .css('background-image', '')
        .css('background-position', ($thumbnail.data('position') || 'center'));

        // Caption.
        s.$slideCaption = s.$slide.find('.caption');

        // Move everything *except* the thumbnail itself to the caption.
        $this.children().not($thumbnail)
        .appendTo(s.$slideCaption);

        // Preload?
        if (_.settings.preload) {

          // Force image to download.
          var $img = $('<img src="' + s.url + '" />');

          // Set slide's background image to it.
          s.$slideImage
          .css('background-image', 'url(' + s.url + ')');

          // Mark slide as loaded.
          s.$slide.addClass('loaded');
          s.loaded = true;

        }

        // Add to slides array.
        _.slides.push(s);

        // Set thumbnail's index.
        $thumbnail.data('index', _.slides.length - 1);

      });

    },

    /**
     * Initialize stuff.
     */
    init: function () {

      // IE<10: Zero out transition delays.
      if (skel.vars.IEVersion < 10) {

        _.settings.slideDuration = 0;
        _.settings.layoutDuration = 0;

      }

      // Skel.
      skel.breakpoints({
        xlarge: '(max-width: 1680px)',
        large: '(max-width: 1280px)',
        medium: '(max-width: 980px)',
        small: '(max-width: 736px)',
        xsmall: '(max-width: 480px)'
      });

      // Everything else.
      _.initProperties();
      _.initViewer();
      _.initEvents();

      // Initial slide.
      window.setTimeout(function () {

        // Show first slide if xsmall isn't active or it just deactivated.
        skel.on('-xsmall !xsmall', function () {

          if (_.current === null) {
            _.switchTo(0, true);
          }

        });

      }, 0);

    },

    /**
     * Switch to a specific slide.
     * @param {integer} index Index.
     */
    switchTo: function (index, noHide) {

      // Already at index and xsmall isn't active? Bail.
      if (_.current == index
          && !skel.breakpoint('xsmall').active) {
        return;
      }

      // Locked? Bail.
      if (_.locked) {
        return;
      }

      // Lock.
      _.locked = true;

      // Hide main wrapper if medium is active.
      if (!noHide
          && skel.breakpoint('medium').active
          && skel.vars.IEVersion > 8) {
        _.hide();
      }

      // Get slides.
      var oldSlide = (_.current !== null ? _.slides[_.current] : null),
          newSlide = _.slides[index];

      // Update current.
      _.current = index;

      // Deactivate old slide (if there is one).
      if (oldSlide) {

        // Thumbnail.
        oldSlide.$parent
        .removeClass('active');

        // Slide.
        oldSlide.$slide.removeClass('active');

      }

      // Activate new slide.

      // Thumbnail.
      newSlide.$parent
      .addClass('active')
      .focus();

      // Slide.
      var f = function () {

        // Old slide exists? Detach it.
        if (oldSlide) {
          oldSlide.$slide.detach();
        }

        // Attach new slide.
        newSlide.$slide.appendTo(_.$viewer);

        // New slide not yet loaded?
        if (!newSlide.loaded) {

          window.setTimeout(function () {

            // Mark as loading.
            newSlide.$slide.addClass('loading');

            // Wait for it to load.
            $('<img src="' + newSlide.url + '" />').on('load', function () {
              //window.setTimeout(function() {

              // Set background image.
              newSlide.$slideImage
              .css('background-image', 'url(' + newSlide.url + ')');

              // Mark as loaded.
              newSlide.loaded = true;
              newSlide.$slide.removeClass('loading');

              // Mark as active.
              newSlide.$slide.addClass('active');

              // Unlock.
              window.setTimeout(function () {
                _.locked = false;
              }, 100);

              //}, 1000);
            });

          }, 100);

        }

        // Otherwise ...
        else {

          window.setTimeout(function () {

            // Mark as active.
            newSlide.$slide.addClass('active');

            // Unlock.
            window.setTimeout(function () {
              _.locked = false;
            }, 100);

          }, 100);

        }

      };

      // No old slide? Switch immediately.
      if (!oldSlide) {
        (f)();
      }// Otherwise, wait for old slide to disappear first.
      else {
        window.setTimeout(f, _.settings.slideDuration);
      }

    },

    /**
     * Switches to the next slide.
     */
    next: function () {

      // Calculate new index.
      var i, c = _.current, l = _.slides.length;

      if (c >= l - 1) {
        i = 0;
      } else {
        i = c + 1;
      }

      // Switch.
      _.switchTo(i);

    },

    /**
     * Switches to the previous slide.
     */
    previous: function () {

      // Calculate new index.
      var i, c = _.current, l = _.slides.length;

      if (c <= 0) {
        i = l - 1;
      } else {
        i = c - 1;
      }

      // Switch.
      _.switchTo(i);

    },

    /**
     * Switches to slide "above" current.
     */
    up: function () {

      // Fullscreen? Bail.
      if (_.$body.hasClass('fullscreen')) {
        return;
      }

      // Calculate new index.
      var i, c = _.current, l = _.slides.length,
          tpr = _.settings.thumbnailsPerRow;

      if (c <= (tpr - 1)) {
        i = l - (tpr - 1 - c) - 1;
      } else {
        i = c - tpr;
      }

      // Switch.
      _.switchTo(i);

    },

    /**
     * Switches to slide "below" current.
     */
    down: function () {

      // Fullscreen? Bail.
      if (_.$body.hasClass('fullscreen')) {
        return;
      }

      // Calculate new index.
      var i, c = _.current, l = _.slides.length,
          tpr = _.settings.thumbnailsPerRow;

      if (c >= l - tpr) {
        i = c - l + tpr;
      } else {
        i = c + tpr;
      }

      // Switch.
      _.switchTo(i);

    },

    /**
     * Shows the main wrapper.
     */
    show: function () {

      // Already visible? Bail.
      if (!_.$body.hasClass('fullscreen')) {
        return;
      }

      // Show main wrapper.
      _.$body.removeClass('fullscreen');

      // Focus.
      _.$main.focus();

    },

    /**
     * Hides the main wrapper.
     */
    hide: function () {

      // Already hidden? Bail.
      if (_.$body.hasClass('fullscreen')) {
        return;
      }

      // Hide main wrapper.
      _.$body.addClass('fullscreen');

      // Blur.
      _.$main.blur();

    },

    /**
     * Toggles main wrapper.
     */
    toggle: function () {

      if (_.$body.hasClass('fullscreen')) {
        _.show();
      } else {
        _.hide();
      }

    },

  };
  return _;
})(jQuery);
main.init();